package com.quan.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.quan.commons.core.bean.R;
import com.quan.commons.core.biz.support.MyBaseServiceImpl;
import com.quan.commons.core.constant.CommonsConstant;
import com.quan.commons.core.exception.BizException;
import com.quan.commons.core.properties.SystemValueProperties;
import com.quan.commons.core.utils.*;
import com.quan.system.entity.*;
import com.quan.system.service.*;
import com.sun.xml.bind.v2.runtime.output.SAXOutput;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;

import com.quan.system.commons.vo.SysUserVo;
import com.quan.system.mapper.SysUserMapper;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;


@Slf4j
@Service
public class SysUserServiceImpl extends MyBaseServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    @Autowired
	private SysUserMapper mapper;

    @Autowired
    private SysUserRoleService sysUserRoleService;

    @Autowired
    private SysRolePermissionService sysRolePermissionService;

    @Autowired
    private SysRoleService sysRoleService;

    @Autowired
    private SysPermissionService sysPermissionService;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private SystemValueProperties properties;

    @Override
    public boolean removeByIds(Collection<? extends Serializable> idList) {
        boolean falg = super.removeByIds(idList);

        idList.forEach(id -> {
            this.sysUserRoleService.deleteByUserId(id);
        });

        return falg;
    }


    @Override
    public List<SysUserVo> queryList(PageUtils pageUtils, SysUserVo vo) {
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<SysUser>(vo);

        List<SysUser> list = super.list(pageUtils, queryWrapper);
        List<SysUserVo> collect = list.stream().map(item -> {
            SysUserVo bean = new SysUserVo();
            BeanUtils.copyProperties(item, bean);
            return bean;
        }).collect(Collectors.toList());

        return collect;
    }

    @Override
    public PageUtils queryPage(PageUtils pageUtils, SysUserVo vo) {
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<SysUser>(vo);

        if(StringUtils.isNotBlank(vo.getKeyword())) {
            queryWrapper.and(w -> {
                w.like("username", vo.getKeyword());
            });
        }

        final IPage<SysUser> page = super.selectPage(pageUtils, queryWrapper);

        PageUtils ps = new PageUtils(page);

        final List<SysUser> records = page.getRecords();

        final List<SysUser> collect = records.stream().map((item) -> {
            SysUserVo bean = new SysUserVo();
            BeanUtils.copyProperties(item, bean);

            // 获取用户对应的角色
            final List<SysUserRole> userRoleIds = this.sysUserRoleService.getRoleIdsByUserId(item.getId());
            final List<Long> roleIds = userRoleIds.stream().map(r -> r.getRoleId()).collect(Collectors.toList());
            if(null != roleIds && !roleIds.isEmpty()) {
                bean.setRoles(this.sysRoleService.getRoles(roleIds));
            }

            return bean;
        }).collect(Collectors.toList());

        ps.setRecords(collect);
        return ps;
    }

    @Transactional
    @Override
    public void updateUser(SysUserVo vo) {

        this.sysUserRoleService.deleteByUserId(vo.getId());
        super.updateById(vo);

        List<SysUserRole> list = new ArrayList<>();
        if(null != vo.getRoleIds()) {
            for (Long roleId : vo.getRoleIds()) {
                SysUserRole entity = new SysUserRole();
                entity.setUserId(vo.getId());
                entity.setRoleId(roleId);
                list.add(entity);
            }
            this.sysUserRoleService.saveBatch(list);
        }

    }

    @Override
    public void saveUser(SysUserVo vo) {

        // 加密盐
        vo.setSalt(RandomUitl.uuid());
        // 默认密码：123456
        String password = StringUtils.isNotBlank(vo.getPassword()) ? vo.getPassword() : "123456";
        // 密码加密
        vo.setPassword(PasswordUtils.encodePassword(password, vo.getSalt()));

        super.save(vo);

        List<SysUserRole> list = new ArrayList<>();
        if(null != vo.getRoleIds()) {
            for (Long roleId : vo.getRoleIds()) {
                SysUserRole entity = new SysUserRole();
                entity.setUserId(vo.getId());
                entity.setRoleId(roleId);
                list.add(entity);
            }
            this.sysUserRoleService.saveBatch(list);
        }
    }

    @Override
    public SysUser getUser(String username) {
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<SysUser>();
        queryWrapper.eq("username", username);
        return super.getOne(queryWrapper);
    }

    @Override
    public String login(SysUserVo vo) {
        final String username = vo.getUsername();
        final String password = vo.getPassword();

        if(StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
            throw new BizException(20001, "账号和密码不能为空");
        }

        SysUser user = this.getUser(username);

        // 判断用户是否存在
        if(null == user) {
            throw new BizException(20001, "用户不存在");
        }
        // 验证密码是否正确
        if (!PasswordUtils.isPasswordValid(user.getPassword(), password, user.getSalt())) {
            throw new BizException(20001, "登录失败，账号或密码不正确！");
        }
        // 判断用户账号状态
        if (user.getStatus() == 0) {
            throw new BizException(20001, "账号已锁定，请联系管理员！");
        }

        Map<String, Object> map = new HashMap<String, Object>();
        map.put("id", user.getId());
        map.put("username", user.getUsername());

        final String token = JwtUtils.createToken(map, this.properties.getJwt().getSecret());

        // 将token保存到缓存中
        this.redisUtils.set(CommonsConstant.RedisPrefix.SSO_TOKEN + ":" + user.getId(), token, this.properties.getJwt().getTimeout());

        return token;
    }

    /**
     * 根据 token 获取用户登录信息
     * @param token
     * @return
     */
    @Override
    public SysUserVo getUserInfoByToken(String token) {
        final String userId = JwtUtils.getUserId(token, this.properties.getJwt().getSecret());
        final SysUser user = super.getById(userId);
        user.setPassword(null);

        SysUserVo vo = new SysUserVo();
        BeanUtils.copyProperties(user, vo);

        return vo;
    }

    /**
     * 获取用户角色
     * @param userId
     * @return
     */
    @Override
    public List<SysRole> getUserRoles(Long userId) {

        QueryWrapper<SysUserRole> userRoleQueryWrapper = new QueryWrapper<SysUserRole>() ;
        userRoleQueryWrapper.eq("user_id", userId).select("role_id");
        final List<SysUserRole> sysUserRoles = this.sysUserRoleService.list(userRoleQueryWrapper);

        if(null != sysUserRoles && !sysUserRoles.isEmpty()) {
            // 获取用户的所有角色
            return this.sysRoleService.list(new QueryWrapper<SysRole>().in("id", sysUserRoles.stream().map(item -> item.getRoleId()).collect(Collectors.toList())));

        }
        return null;
    }

    /**
     * 获取用户权限
     * @param userId
     * @return
     */
    @Override
    public List<SysPermission> getUserPermissions(Long userId) {
        QueryWrapper<SysUserRole> userRoleQueryWrapper = new QueryWrapper<SysUserRole>() ;
        userRoleQueryWrapper.eq("user_id", userId).select("role_id");
        final List<SysUserRole> sysUserRoles = this.sysUserRoleService.list(userRoleQueryWrapper);

        if(null != sysUserRoles && !sysUserRoles.isEmpty()) {
            // 获取用户的角色ID
            final List<Long> roleIds = sysUserRoles.stream().map(item -> item.getRoleId()).collect(Collectors.toList());

            // 获取用户的角色对应的权限关系
            QueryWrapper<SysRolePermission> sysRolePermissionQueryWrapper = new QueryWrapper<SysRolePermission>() ;
            sysRolePermissionQueryWrapper.in("role_id", roleIds).select("permission_id");
            final List<SysRolePermission> sysRolePermissions = this.sysRolePermissionService.list(sysRolePermissionQueryWrapper);

            if(null != sysRolePermissions && !sysRolePermissions.isEmpty()) {

                final List<Long> permitssionIds = sysRolePermissions.stream().map(item -> item.getPermissionId()).collect(Collectors.toList());
                // 获取用户的权限
                QueryWrapper<SysPermission> sysPermissionQueryWrapper = new QueryWrapper<SysPermission>() ;
                sysPermissionQueryWrapper.in("id", permitssionIds);
                return this.sysPermissionService.list(sysPermissionQueryWrapper);

            }

        }
        return null;
    }

    /**
     * 获取用户与权限的关系数据
     * @param roles
     * @return
     */
    @Override
    public List<SysRolePermission> getUserPermissionsRelation(List<SysRole> roles) {
        List<Long> roleIds = new ArrayList<Long>() ;
        roles.forEach(item -> {
            roleIds.add(item.getId());
        });

        QueryWrapper<SysRolePermission> queryWrapper = new QueryWrapper<SysRolePermission>() ;
        queryWrapper.in("role_id", roleIds) ;
        return this.sysRolePermissionService.list(queryWrapper);
    }


    @Override
    public boolean hasFieldValue(String field, Object value) {
        return super.hasExist(field, value, SysUser.class);
    }

    @Override
    public boolean hasFieldValueForUpdate(Long id, String field, Object value) {
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<SysUser>();
        queryWrapper.eq(field, value).ne("id", id);
        if(super.count(queryWrapper) > 0) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public void updatePassword(Long id, String oldPassword, String newPassword) {
        SysUser entity = super.getById(id);

        if (null != entity && entity.getId() != null) {
            if (!PasswordUtils.isPasswordValid(entity.getPassword(), oldPassword, entity.getSalt())) {
                throw new RuntimeException("新密码与原密码不一致");
            }

            String salt = RandomUitl.uuid();
            // 密码加盐组成加密密码
            String encodePassword = PasswordUtils.encodePassword(newPassword, salt);

            SysUser newEntity = new SysUser();
            newEntity.setId(id);
            newEntity.setPassword(encodePassword);
            newEntity.setSalt(salt);

            super.updateById(newEntity);
        } else {
            throw new RuntimeException("修改密码失败");
        }

    }

    @Override
    public boolean batchResetPassword(List<Long> idList) {
        boolean flag = true;
        if(null != idList && !idList.isEmpty()) {
            for (Long id : idList) {

                SysUser entity = super.getById(id) ;
                // 加密盐
                entity.setSalt(RandomUitl.uuid());
                // 默认密码：123456
                String password = "123456";
                // 密码加密
                entity.setPassword(PasswordUtils.encodePassword(password, entity.getSalt()));

                flag = super.updateById(entity);

                //if (flag) {
                //    // 发送短信或邮件告知用户账号和密码
                //    Map<String, Object> map = new HashMap<String, Object>();
                //    map.put("subject", "综合管理系统.密码重置");
                //    map.put("realname", entity.getRealname());
                //    map.put("username", entity.getUsername());
                //    map.put("password", password);
                //
                //    MailVo mailBean = new MailVo();
                //    mailBean.setTo(entity.getEmail());
                //    mailBean.setSubject(map.get("subject").toString());
                //    mailBean.setTemplateLocation("mail/account.html");
                //    mailBean.setTemplateData(map);
                //
                //    this.producerMessageSendMail.sender(mailBean);
                //}
            }
        }
        return flag;
    }

    @Override
    public void changeStatus(Long id, Integer status) {
        UpdateWrapper<SysUser> updateWrapper = new UpdateWrapper<SysUser>();
        updateWrapper.eq("id", id);
        updateWrapper.set("status", status);
        super.update(updateWrapper);
    }
}